package com.gaff.emp.core.sftp;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import com.gaff.emp.core.EmpException;
import com.jcraft.jsch.*;
import lombok.extern.slf4j.Slf4j;

import java.io.*;
import java.util.Arrays;

@Slf4j
public class SftpClient {

    private SftpProperties properties;

    public SftpClient(SftpProperties properties) {
        this.properties = properties;
    }

    public ChannelSftp getSftpChannel() {
        ChannelSftp sftp = null;
        try {
            sftp = createSftp();
            sftp.cd(properties.getHomeDir());
            return sftp;
        } catch (Exception e) {
            log.error("ftp connect failure",e);
        }
        return null;
    }

    public void uploadFile(String targetPath, byte[] data) {
        uploadFile(targetPath, new ByteArrayInputStream(data));
    }

    public void uploadFile(String targetPath, File file) throws Exception {
        uploadFile(targetPath, new FileInputStream(file));
    }

    public void uploadFile(String targetPath, InputStream inputStream) {
        ChannelSftp sftp = getSftpChannel();
        uploadFile(sftp, targetPath, inputStream);
        disconnect(sftp);
    }

    public void uploadFile(ChannelSftp sftp, String targetPath, InputStream inputStream) {
        log.info("uploadFile targetPath==="+targetPath);
        String fileName = targetPath;
        int index = targetPath.lastIndexOf("/");
        if (index != -1) {
            String fileDir = targetPath.substring(0, index);
            if (!createDirs(fileDir, sftp)) {
                throw new EmpException("Upload File failure");
            }
            fileName = targetPath.substring(index + 1);
        }
        try {
            sftp.put(inputStream, fileName);
            sftp.cd(properties.getHomeDir());
        } catch (Exception e) {
            throw new EmpException("Upload File failure"+e.getMessage());
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                }
            }
        }
    }

    public void downloadFile(String targetFile, String destFile) {
        ChannelSftp sftp = getSftpChannel();
        OutputStream outputStream = null;
        try {
            outputStream = new FileOutputStream(destFile);
            sftp.get(targetFile, outputStream);
        } catch (Exception e) {
            throw new EmpException("Download File failure", e);
        } finally {
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                }
            }
            disconnect(sftp);
        }
    }

    public void deleteFile(String targetPath) throws EmpException {
        ChannelSftp sftp = getSftpChannel();
        deleteFile(sftp, targetPath);
        disconnect(sftp);
    }

    public void deleteFile(ChannelSftp sftp, String targetPath) throws EmpException {
        log.info("deleteFile targetPath==="+targetPath);
        try {
            sftp.rm(targetPath);
        } catch (Exception e) {
            throw new EmpException("Delete File failure"+e.getMessage());
        }
    }

    private boolean createDirs(String dirPath, ChannelSftp sftp) {
        if (dirPath != null && !dirPath.isEmpty() && sftp != null) {
            String[] dirs = Arrays.stream(dirPath.split("/"))
                    .filter(StrUtil::isNotBlank)
                    .toArray(String[]::new);
            for (String dir : dirs) {
                try {
                    sftp.cd(dir);
                } catch (Exception e) {
                    try {
                        sftp.mkdir(dir);
                    } catch (SftpException e1) {
                    }
                    try {
                        sftp.cd(dir);
                    } catch (SftpException e1) {
                    }
                }
            }
            return true;
        }
        return false;
    }

    private ChannelSftp createSftp() throws Exception {
        JSch jsch = new JSch();
        Session session = createSession(jsch, properties.getHost(), properties.getUsername(), properties.getPort());
        session.setPassword(properties.getPassword());
        session.connect(properties.getConnectTimeout());
        Channel channel = session.openChannel("sftp");
        channel.connect(properties.getConnectedTimeout());
        return (ChannelSftp) channel;
    }

    private Session createSession(JSch jsch, String host, String username, Integer port) throws Exception {
        Session session = null;
        if (port <= 0) {
            session = jsch.getSession(username, host);
        } else {
            session = jsch.getSession(username, host, port);
        }
        if (session == null) {
            throw new EmpException(host + " session is null");
        }
        session.setConfig("StrictHostKeyChecking", "no");
        return session;
    }

    public void disconnect(ChannelSftp sftp) {
        try {
            if (sftp != null) {
                if (sftp.isConnected()) {
                    sftp.disconnect();
                } else if (sftp.isClosed()) {
                    log.info("sftp is closed already");
                }
                if (null != sftp.getSession()) {
                    sftp.getSession().disconnect();
                }
            }
        } catch (JSchException e) {
        }
    }

    public static void test(String targetFile, String destFile) {
        if (destFile.endsWith(File.separator)) {
            int index = targetFile.lastIndexOf("/");
            if (index != -1) {
                destFile = destFile + targetFile.substring(index + 1);
            } else {
                destFile = destFile + targetFile;
            }
        }
    }

    public static void main(String[] args) throws Exception {
        String str = "message|ssss";
        String messages[] = str.split("\\|");
        System.out.println(messages[0]);
//        FileOutputStream fileOutputStream = new FileOutputStream();
        FileUtil.writeUtf8String("aaa", "D:\\tmp\\test.txt");
        test("/root/asd/asd", "asdads\\asd\\asd.txt\\");
//        String ss ="sewrewr@@serer";
//        System.out.println(ss.split("@@")[1]);
//        SftpProperties properties = new SftpProperties();
//        properties.setUsername("root");
//        properties.setPassword("root123");
//        properties.setHost("192.168.0.19");
//        properties.setPort(22);
//        properties.setHomeDir("/root");
//        properties.setConnectedTimeout(2000);
//        properties.setConnectTimeout(2000);
//        SftpClient sftpClient = new SftpClient(properties);
////        sftpClient.uploadFile("MobaXterm.ini", new File("C:\\Users\\ckm\\Desktop\\MobaXterm.ini"));
////        sftpClient.uploadFile("test/MobaXterm.ini", new File("C:\\Users\\ckm\\Desktop\\MobaXterm.ini"));
////        sftpClient.downloadFile("MobaXterm.ini");
////        sftpClient.downloadFile("test/MobaXterm.ini");
////        sftpClient.deleteFile("MobaXterm.ini");
//        sftpClient.deleteFile("test/MobaXterm111.ini");

    }

}
